package com.opencee.cloud.base.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.opencee.cloud.base.entity.BaseApplicationEntity;
import com.opencee.cloud.base.entity.BaseSystemEntity;
import org.apache.commons.io.FileUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @author liuyadu
 * @date 2021/12/17
 */
@Service
public class CodeGeneratorService {

    public static final String[] fileNames = new String[]{
            "vue.config.js",
            "package.json",
            ".env.development",
            ".env.local",
            ".env.production",
            ".env.test",
            "settings.js",
    };

    public File downloadTemplateVue(BaseSystemEntity system, BaseApplicationEntity application) {
        try {
            String targetFilePath = System.getProperty("java.io.tmpdir") + "generator-vue" + File.separatorChar + System.currentTimeMillis();
            File targetFile = new File(targetFilePath);
            if (!targetFile.exists()) {
                targetFile.mkdirs();
            }
            List<String> tplFileList = new ArrayList<>(Arrays.asList(fileNames));
            this.copyDirToDirFromJar("templates/vue", targetFilePath);
            List<File> files = FileUtil.loopFiles(targetFile, new FileFilter() {
                @Override
                public boolean accept(File file) {
                    return tplFileList.contains(file.getName());
                }
            });
            // 随机端口
            String port = RandomUtil.randomNumbers(4);
            Map<String, String> map = new HashMap(8);
            String name = system.getSid() + "-vue";
            map.put("port", port);
            map.put("app_key", application.getAppKey());
            map.put("sid", system.getSid());
            map.put("name", name);
            map.put("title", system.getName());
            files.forEach(f -> {
                String str = FileUtil.readUtf8String(f);
                // 替换变量
                String content = StrUtil.format(str, map);
                // 重新写入文件
                FileUtil.writeUtf8String(content, f);
            });

            // 打包
            String zipSrc = targetFilePath + File.separatorChar + "templates/vue";
            File zipSrcFile = new File(zipSrc);
            if (!zipSrcFile.exists()) {
                zipSrcFile.mkdirs();
            }
            String zipDest = targetFilePath + File.separatorChar + name + ".zip";
            ZipUtil.zip(zipSrc, zipDest, false);
            return new File(zipDest);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 复制path目录下所有文件
     *
     * @param sourceDir 文件目录 不能以/开头
     * @param targetDir 新文件目录
     */
    public void copyDirToDirFromJar(String sourceDir, String targetDir) {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            //获取所有匹配的文件
            Resource[] resources = resolver.getResources(sourceDir + "/*");
            extracted(sourceDir, resources, targetDir);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void extracted(String sourceDir, Resource[] resources, String targetDir) throws IOException {
        for (int i = 0; i < resources.length; i++) {
            Resource resource = resources[i];
            //以jar运行时，resource.getFile().isFile() 无法获取文件类型，会报异常，抓取异常后直接生成新的文件即可；以非jar运行时，需要判断文件类型，避免如果是目录会复制错误，将目录写成文件。
            if (resource.getFile().isFile()) {
                InputStream stream = resource.getInputStream();
                String parent = resource.getFile().getParent();
                String reg = sourceDir.replace("/", File.separator);
                parent = parent.substring(parent.indexOf(reg));
                String destPath = targetDir + File.separator + parent + File.separator + resource.getFilename();
                System.out.println(destPath);
                FileUtils.copyToFile(stream, new File(destPath));
            } else {
                File[] files = resource.getFile().listFiles();
                Resource[] rs = new Resource[files.length];
                for (int j = 0; j < files.length; j++) {
                    rs[j] = new FileSystemResource(files[j]);
                }
                extracted(sourceDir, rs, targetDir);
            }
        }
    }

    public static void main(String[] args) {
        CodeGeneratorService generatorService = new CodeGeneratorService();
        BaseSystemEntity system = new BaseSystemEntity();
        BaseApplicationEntity application = new BaseApplicationEntity();
        system.setName("项目名称");
        system.setSid("test-demo");
        application.setAppKey("adasdadadsadas");
        generatorService.downloadTemplateVue(system, application);

    }
}
